package test.functional;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import test.utils.RandomTestDataUtils;

import com.fitso.model.bean.User;
import com.fitso.model.service.user.UserService;

@RunWith(Parameterized.class)
public class User_IT {

	protected static final int DATA_SIZE = 10;

	protected UserService _userService;

	@Parameters
	public static Collection<Object[]> data() {
		List<Object[]> data = new ArrayList<Object[]>();

		for (int i = 0; i < DATA_SIZE; i++) {
			Object[] datum = new Object[4];
			datum[0] = RandomTestDataUtils.randomEmail(10, 8); // email
			datum[1] = RandomTestDataUtils.randomAlphanumeric(12); // password
			datum[2] = RandomTestDataUtils.randomAlphabetic(8); // first name
			datum[3] = RandomTestDataUtils.randomAlphabetic(12); // last name
			data.add(datum);
		}
		return data;
	}

	protected String _email, _password, _firstName, _lastName;
	protected User _user;

	public User_IT(String email, String password, String firstName, String lastName) {
		_user = new User(firstName, lastName, email, password);
		_email = email;
		_password = password;
		_firstName = firstName;
		_lastName = lastName;
	}

	protected static ApplicationContext context = new ClassPathXmlApplicationContext("fitso-model-context.xml");

	@Before
	public void setUp() throws Exception {
		_userService = (UserService) context.getBean("SecureUserService");
	}

	@After
	public void tearDown() throws Exception {
		_userService.delete(_user);
	}

	@Test(timeout = 2000)
	public void test_round_tripping_user() {
		// add the new user
		_userService.save(_user);

		// fetch the just added user
		User fetchedUser = _userService.fetch(_email, _password);
		assertThat(_user, equalTo(fetchedUser));

		// password should be encrypted and no longer in the open
		assertThat(_password, not(equalTo(fetchedUser.getPassword())));

		// change the user name
		_user.setFirstName(RandomTestDataUtils.randomAlphabetic(8));
		_user.setLastName(RandomTestDataUtils.randomAlphabetic(12));
		_userService.edit(_user);

		fetchedUser = _userService.fetch(_email, _password);
		assertThat(_user, equalTo(fetchedUser));

		// change the user email
		_email = RandomTestDataUtils.randomEmail(14, 20);
		_user.setEmail(_email);
		_userService.edit(_user);

		fetchedUser = _userService.fetch(_email, _password);
		assertThat(_user, equalTo(fetchedUser));

		// change the user password
		String newPass = RandomTestDataUtils.randomAlphanumeric(12);
		_user.setPassword(newPass);
		_userService.edit(_user);

		fetchedUser = _userService.fetch(_email, newPass);
		assertThat(_user, equalTo(fetchedUser));
		
		// password should be encrypted and no longer in the open
		assertThat(newPass, not(equalTo(fetchedUser.getPassword())));
	}
}
